﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Security;
using AutoMapper;
using AutoPartsSearch.Domain.Abstract.Repositories;
using AutoPartsSearch.Domain.Entities;
using AutoPartsSearch.Domain.Entities.Enums;
using AutoPartsSearch.Domain.Exceptions;
using AutoPartsSearch.Web.ViewModels.AccountModels;
using AutoPartsSearch.Domain.Abstract;
using AutoPartsSearch.Web.ViewModels.SellerModels;
using AutoPartsSearch.Domain.Common;
using System.Security.Principal;

namespace AutoPartsSearch.Web.Controllers
{
    public class AccountController : Controller
    {
        private readonly IMembership _membership;
        private readonly ISellerRepository _sellerRepository;
        private ISellerGetter _sellerGetter;
        private readonly IConfigurationGetter _configurationGetter;
        private readonly IMessageSender _messageSender;
        private readonly IMessageBuilder _messageBuilder;

        public AccountController(IMembership membership, 
            ISellerRepository sellerRepository, 
            ISellerGetter sellerGetter, 
            IConfigurationGetter configurationGetter,
            IMessageSender messageSender,
            IMessageBuilder messageBuilder)
        {
            this._membership = membership;
            this._sellerRepository = sellerRepository;
            this._sellerGetter = sellerGetter;
            this._configurationGetter = configurationGetter;
            this._messageBuilder = messageBuilder;
            this._messageSender = messageSender;
        }

        public ActionResult LogOn()
        {
            return View();
        }

        [HttpPost]
        public ActionResult LogOn(LogOn model, string returnUrl)
        {
            if (ModelState.IsValid)
            {
                var userName = _membership.GetUserNameByEmail(model.UserName);
                if (userName != null)
                {
                    if (_membership.ValidateUser(userName, model.Password))
                    {
                        _membership.SetCookie(userName, model.RememberMe);
                        if (Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1 && returnUrl.StartsWith("/")
                            && !returnUrl.StartsWith("//") && !returnUrl.StartsWith("/\\"))
                        {
                            return Redirect(returnUrl);
                        }
                        if (_membership.IsUserInRole(userName, Role.Administrator))
                        {
                            return RedirectToAction("Index", "Home", new {area = "Administration"});
                        }
                        return RedirectToAction("List", "SellerSearchQuery");
                    }
                }
                ModelState.AddModelError("", "The email or password provided is incorrect.");
            }
            return View(model);
        }

        public ActionResult LogOff()
        {
            _membership.SignOut();
            return RedirectToAction("Index", "SearchQuery");
        }

        public ViewResult Create()
        {
            return View();
        }

        [HttpPost]
        public ActionResult Create(Register registerSeller)
        {
            if (ModelState.IsValid)
            {
                registerSeller.IsDeliveryOnlyToRegion = false;
                var seller = Mapper.Map<Seller>(registerSeller);
                seller.Expired = DateTime.Now.AddDays(GetFreeDaysForSeller());
                try
                {
                    //using (var scope = TransactionUtils.CreateTransactionScope())
                    //{
                        this._membership.CreateUser(registerSeller.CompanyName, registerSeller.Password, registerSeller.EMail);
                        this._membership.AddRoleToUser(registerSeller.CompanyName, Role.Seller);
                        this._sellerRepository.Add(seller);
                        this._membership.SetCookie(registerSeller.CompanyName, false);
                    //    scope.Complete();
                    //}
                    return View("Success");
                }
                catch (CreateUserFailedException exception)
                {
                    ModelState.AddModelError(string.Empty, exception.Message);
                    return View(registerSeller);
                }
            }
            return View(registerSeller);
        }

        [Authorize(Roles = Role.Seller)]
        public ActionResult Details(IPrincipal user)
        {
            var seller = _sellerGetter.GetSellerByUser(user);
            var sellerInfo = Mapper.Map<SellerInfo>(seller);
            return View(sellerInfo);
        }

        [Authorize(Roles = Role.Seller)]
        [HttpPost]
        public ActionResult UpdateAccount(SellerInfo sellerInfo, IPrincipal user)
        {
            if (!sellerInfo.CompanyName.Equals(user.Identity.Name, StringComparison.CurrentCulture))
            {
                throw new ArgumentException("Company name should be the same as current user.", "sellerInfo");
            }
            sellerInfo.IsDeliveryOnlyToRegion = false;
            var seller = Mapper.Map<Seller>(sellerInfo);
            this._sellerRepository.Update(seller);
            return RedirectToAction("Details");
        }

        [Authorize(Roles = Role.Seller)]
        public ActionResult ChangePassword()
        {
            return View();
        }

        [Authorize(Roles = Role.Seller)]
        [HttpPost]
        public ActionResult ChangePassword(ChangePassword model, IPrincipal user)
        {
            if (ModelState.IsValid)
            {
                bool changePasswordSucceeded;
                try
                {
                    MembershipUser currentUser = Membership.GetUser(User.Identity.Name, true /* userIsOnline */);
                    changePasswordSucceeded = currentUser.ChangePassword(model.OldPassword, model.NewPassword);
                }
                catch (Exception)
                {
                    changePasswordSucceeded = false;
                }

                if (changePasswordSucceeded)
                {
                    return RedirectToAction("Details");
                }
                else
                {
                    ModelState.AddModelError("", "The current password is incorrect or the new password is invalid.");
                }
            }

            // If we got this far, something failed, redisplay form
            return View(model);
        }

        [Authorize]
        public ActionResult Expired()
        {
            return View();
        }

        public ActionResult ResetPassword()
        {
            return View();
        }

        [HttpPost]
        public ActionResult ResetPassword(string email)
        {
            if (!string.IsNullOrEmpty(email))
            {
                var userName = _membership.GetUserNameByEmail(email);
                if (userName != null)
                {
                    var newPassword = _membership.ResetPassword(userName);
                    if (newPassword != null)
                    {
                        var message = _messageBuilder.BuildResetPasswordMessage(email, newPassword);
                        _messageSender.Send(message);
                        return View("ResetPasswordResult");
                    }
                }
            }
            ModelState.AddModelError("", "");
            return View((object)email);
        }

        private int GetFreeDaysForSeller()
        {
            int freeDays;
            if (!int.TryParse(_configurationGetter.GetConfigurationValue(Constants.FreePeriodInDays), out freeDays))
            {
                freeDays = 90;
            }
            return freeDays;
        }

    }
}
